import { OperatorManager } from "../operators/operatorManager";
import { AppAisle } from "@lib/alen-helper/node/appAisle";
import { RunTime } from "../runtime";
import { BaseController } from "./baseController";


export namespace BaseCmdHandlers {
    export type BaseHandlers = AppAisle.CmdHandlers<Runtime.Controller.BaseCmdData<''>>;
    export type Handlers<T extends string> = {
        [K in keyof BaseHandlers as `${T}${string & K}`]: BaseHandlers[K];
    };

    export interface Options {

    }
}

export class BaseCmdHandlers implements BaseCmdHandlers.BaseHandlers {
    constructor(
        public readonly options: Partial<BaseCmdHandlers.Options>,
        public readonly runTime: RunTime,
        public readonly controller: BaseController<OperatorManager.OperatorType, {}>
    ) {

    }
    private _getApp(aisle: AppAisle<AppAisle.Cmds>) {
        const app = this.runTime.getApp(aisle);
        if (!app || !app.id) throw new Error('找不到APP');
        return app;
    }

    _destroy: BaseCmdHandlers.Handlers<''>['_destroy'] = (data, aisle) => {
        const app = this._getApp(aisle);
        return this.controller.destroy(app.id!, data.data.param.id);
    }

    _state: BaseCmdHandlers.Handlers<''>['_state'] = (data, aisle) => {
        const app = this._getApp(aisle);
        return this.controller.getState(app.id!, data.data.param.id);
    }
}

export function buildBaseCmdHandlers<T extends string>(
    name: T,
    options: Partial<BaseCmdHandlers.Options>,
    runTime: RunTime,
    controller: BaseController<OperatorManager.OperatorType, {}>
) {
    const eventNames: UnionToTuple<keyof Runtime.Controller.BaseCmdData_Client<''>> = ['_event_build', '_event_destroy', '_event_state'];
    const eventHandlerIds: string[] = [];
    for (let eN of eventNames) {
        const sName: 'window_event_build' = name + eN as any;
        const cName: 'build' = sName.split('_').pop() as any;
        eventHandlerIds.push(
            runTime.sendEvent(
                controller, cName,
                data => runTime.getApp(data.item.appid),
                sName,
                item => ({ appid: item.item.appid, id: item.item.id }),
            )
        );
    }
    const base = new BaseCmdHandlers(options, runTime, controller);
    const key: UnionToTuple<keyof BaseCmdHandlers.BaseHandlers> = ['_destroy', '_state'];
    const handler: AppAisle.CmdHandlers<Runtime.Controller.BaseCmdData<T>> = {} as any;
    for (let k of key) {
        (handler as any)[name + k] = (data: any, ...ps: [any]) => {
            data.data.cmd = k;
            return base[k](data, ...ps);
        };
    }
    return {
        eventHandlerIds,
        handler,
    };
}
